package com.arpa.wms.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.arpa.core.web.MediaTypes;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.Page;
import com.arpa.ntocc.common.common.constant.StrConsts;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.ShipmentWarehouseValidate;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.ntocc.common.common.util.excel.EasyExcelUtil;
import com.arpa.ntocc.common.security.annotation.NeedLogin;
import com.arpa.ntocc.common.security.annotation.NoReSubmit;
import com.arpa.wms.domain.consts.CommonConst;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.consts.PropertyConst;
import com.arpa.wms.domain.dto.DeliveryDTO;
import com.arpa.wms.domain.dto.DeliveryExcelDTO;
import com.arpa.wms.domain.dto.WaveQueryGoodsDTO;
import com.arpa.wms.domain.entity.Delivery;
import com.arpa.wms.domain.enums.DeliveryStatusEnum;
import com.arpa.wms.domain.vo.*;
import com.arpa.wms.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import io.swagger.annotations.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单 Controller
 * </p>
 *
 * @author LEO
 * @since 2020-08-07
 */
@Api(tags = "订单管理")
@RestController
@RequestMapping(value = "/delivery", produces = "application/json;charset=UTF-8")
@Log4j2
public class DeliveryController {

    private static final String TIPS = "注：当前选择订单数量为%d单，%d个货主，%d个承运商，将拆分成%d个波次。";

    @Resource
    public RedissonClient redissonClient;

    @Autowired
    private IDeliveryService iDeliveryService;

    @Autowired
    private IDeliveryDistributionService iDeliveryDistributionService;

    @Autowired
    private TmsWaybillUpdateService tmsWaybillUpdateService;

    @Autowired
    private WaveService waveService;

    @Autowired
    private DeliveryCancelHandleService deliveryCancelHandleService;

    private final static String COMMA = ",";

    /**
     * 获取 出库单 列表
     *
     * @param deliveryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "获取 订单 列表", notes = "获取 订单 列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryVO.class))
    @NeedLogin
    @GetMapping("/list")
    public Result list(DeliveryDTO deliveryDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            String groupCode = UserUtil.getBranchCode();
            List<String> warehouseCodes = authMap.get(CommonConst.WAREHOUSE_CODES);
            List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);

            if(StrUtil.isBlank(groupCode)){
                throw new ServiceException("用户所属组织为空，请重新登录");
            }
            if(IterUtil.isEmpty(warehouseCodes)||IterUtil.isEmpty(shipmentCodes)){
                return Result.ok().data(new Page<>(deliveryDTO.getPageNum(), deliveryDTO.getPageSize()));
            }
            //支持多个承运商查询
            if (StrUtil.isNotEmpty(deliveryDTO.getCarrierCode())) {
                String[] carrierCodes = deliveryDTO.getCarrierCode().split(",");
                List<String> carrierCodeList = new ArrayList<>(Arrays.asList(carrierCodes));
                deliveryDTO.setCarrierCodes(carrierCodeList);
                deliveryDTO.setCarrierCode(StrUtil.EMPTY);
            }
            deliveryDTO.setGroupCode(groupCode);
            deliveryDTO.setShipmentCodes(shipmentCodes);
            deliveryDTO.setWarehouseCodes(warehouseCodes);
            deliveryDTO.setIsCancel(NumConst.NUM_ZERO);
            iDeliveryService.constructParams(deliveryDTO);
            DeliveryVO deliveryVO = iDeliveryService.queryListTotal(deliveryDTO);
            List<DeliveryVO> outboundVOS = iDeliveryService.queryList(deliveryDTO);
            Page<DeliveryVO> returnPage = new Page<>(deliveryDTO.getPageNum(), deliveryDTO.getPageSize());
            returnPage.setRecords(outboundVOS);
            returnPage.setTotal(deliveryVO.getTotal());
            returnPage.setSumObject(deliveryVO);
            return Result.ok().data(returnPage);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 订单 导出
     *
     * @param deliveryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "订单 导出", notes = "获取 订单 列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryVO.class))
    @NeedLogin
    @GetMapping("/importDelivery")
    public Result importDelivery(DeliveryDTO deliveryDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            List<String> warehouseCodes = authMap.get(CommonConst.WAREHOUSE_CODES);
            String groupCode = UserUtil.getBranchCode();
            List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);
            deliveryDTO.setGroupCode(groupCode);
            //登录账号授权的仓库过滤
            deliveryDTO.setWarehouseCodes(warehouseCodes);
            //登录账号授权的货主过滤
            deliveryDTO.setShipmentCodes(shipmentCodes);
            iDeliveryService.constructQueryParams(deliveryDTO);
            DeliveryVO deliveryVO = iDeliveryService.importDeliveryTotal(deliveryDTO);
            List<DeliveryVO> DeliveryVOS = iDeliveryService.importDelivery(deliveryDTO);

            Page<DeliveryVO> returnPage = new Page<>(deliveryDTO.getPageNum(), deliveryDTO.getPageSize());
            returnPage.setRecords(DeliveryVOS);
            returnPage.setTotal(deliveryVO.getTotal());
            returnPage.setSumObject(deliveryVO);
            return Result.ok().data(returnPage);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 提交 出库单
     *
     * @param entity
     * @param request
     * @return 如果是保存操作，status值请传 1 默认是 0
     */
    @ApiOperation(value = "提交 订单 ", notes = "提交 订单 ")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/submit")
    @NoReSubmit
    public Result submit(@RequestBody @Validated(Delivery.Save.class) Delivery entity, HttpServletRequest request) {
        try {
            entity.setGroupCode(UserUtil.getBranchCode());
            entity.setStatus(DeliveryStatusEnum.UN_DISTRIBUTION.getValue());
            return iDeliveryService.saveWithGoods(entity);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 保存 出库单  正常出库单保存操作
     *
     * @param entity
     * @param request
     * @return
     */
    @ApiOperation(value = "保存 出库单 ", notes = "保存 出库单 ")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/save")
    @NoReSubmit
    public Result save(@RequestBody @Validated(Delivery.Save.class) Delivery entity, HttpServletRequest request) {
        try {
            entity.setGroupCode(UserUtil.getBranchCode());
            entity.setStatus(DeliveryStatusEnum.ADD.getValue());
            return iDeliveryService.saveWithGoods(entity);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 获取出库单详情
     *
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "获取订单详情", notes = "获取订单详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "code", value = "出库单code", paramType = "path", dataType = "String")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryWithGoodsVO.class))
    @NeedLogin
    @GetMapping(value = "/detail/{code}")
    public Result detail(@PathVariable String code, HttpServletRequest request) {
        try {
            DeliveryVO deliveryVO = iDeliveryService.getVOByCode(code);
            return Result.ok().data(deliveryVO);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 保存 出库退货单
     *
     * @param entity
     * @param request
     * @return
     */
    @ApiOperation(value = "保存 出库退货单 ", notes = "保存 出库退货单 ")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/refundLocalSave")
    @NoReSubmit
    public Result refundLocalSave(@RequestBody @Validated(Delivery.Save.class) Delivery entity, HttpServletRequest request) {
        try {
            entity.setStatus(DeliveryStatusEnum.ADD.getValue());
            return iDeliveryService.refundSaveOrSubmit(entity, false);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 获取 出库退货单详情 （修改页面请求）
     *
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "获取 出库退货单详情", notes = "获取 出库退货单详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "code", value = "出库单code", paramType = "path", dataType = "String")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryWithGoodsVO.class))
    @NeedLogin
    @GetMapping(value = "/refundDetail/{code}")
    public Result refundDetail(@PathVariable String code, HttpServletRequest request) {
        try {
            DeliveryVO deliveryVO = iDeliveryService.getRefundVOByCode(code);
            return Result.ok().data(deliveryVO);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 提交 出库退货单
     *
     * @param entity
     * @param request
     * @return
     */
    @ApiOperation(value = "提交 出库退货单 ", notes = "提交 出库退货单 ")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/refundSubmit")
    @NoReSubmit
    public Result refundSubmit(@RequestBody @Validated(Delivery.Save.class) Delivery entity, HttpServletRequest request) {
        try {
            entity.setStatus(DeliveryStatusEnum.UN_DISTRIBUTION.getValue());
            return iDeliveryService.refundSaveOrSubmit(entity, true);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 获取订单库存分配详情
     *
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "获取订单库存分配详情", notes = "获取订单库存分配详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "code", value = "出库单code", paramType = "path", dataType = "String")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryWithGoodsVO.class))
    @NeedLogin
    @GetMapping(value = "/distribution/list/{code}")
    public Result distributionList(@PathVariable String code, HttpServletRequest request) {
        try {
            Delivery delivery = iDeliveryService.getOne(new QueryWrapper<Delivery>().lambda().eq(Delivery::getCode, code).eq(Delivery::getDeleted, 0).eq(Delivery::getGroupCode,UserUtil.getBranchCode()));
            if (delivery == null) {
                return Result.error("出库单不存在，请确认");
            }

            DeliveryVO deliveryVO = iDeliveryService.getDeliveryVoByEntity(delivery);
            // 获取带分配信息的明细信息
            List<DeliveryItemWithDistributionVO> deliveryItemWithDistributionVoS = iDeliveryDistributionService.queryWithItemList(delivery.getCode());
            deliveryVO.setDeliveryItemWithDistributionVOList(deliveryItemWithDistributionVoS);

            return Result.ok().data(deliveryVO);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    @ApiOperation(value = "取消分配", notes = "取消分配")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping(value = "/cancel")
    public Result cancelDistribution(@RequestBody DeliveryVO entity, HttpServletRequest request) {
        Result result = iDeliveryService.cancelDistribution(entity);
        return result;
    }


    /**
     * 作废功能
     *
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "作废订单", notes = "作废订单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping(value = "/blank/{code}")
    public Result blank(@PathVariable String code, HttpServletRequest request) {
        if (StringUtils.isBlank(code)) {
            return Result.error("code不能为空");
        }
        Result result = iDeliveryService.blank(code);
        return result;
    }


    @ApiOperation(value = "确认 出货分配 ", notes = "确认 出货分配 ", produces = MediaTypes.JSON_UTF_8)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping(value = "/confirm/{code}")
    public Result confirm(@PathVariable String code, HttpServletRequest request) {
        try {
            Result result = iDeliveryService.confirm(code,UserUtil.getBranchCode());
            return result;
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 获取 可退货出库单 列表
     *
     * @param deliveryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "获取 可退货订单 列表", notes = "获取 可退货订单 列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryVO.class))
    @NeedLogin
    @GetMapping("/findCanRefundList")
    public Result findCanRefundList(DeliveryDTO deliveryDTO, HttpServletRequest request) {
        try {
            // 根据仓库、入驻商、客户、已发数量>退货数量 获取发货单列表
            List<Delivery> deliveries = new ArrayList<>();
            if(StringUtils.isNotBlank(deliveryDTO.getShipmentCode()) && StringUtils.isNotBlank(deliveryDTO.getCustomerCode())
                    && StringUtils.isNotBlank(deliveryDTO.getWarehouseCode())){
                deliveries = iDeliveryService.list(new QueryWrapper<Delivery>().lambda()
                        .eq(Delivery::getWarehouseCode, deliveryDTO.getWarehouseCode())
                        .eq(Delivery::getShipmentCode, deliveryDTO.getShipmentCode())
                        .eq(Delivery::getCustomerCode, deliveryDTO.getCustomerCode())
                        .eq(Delivery::getGroupCode,UserUtil.getBranchCode())
                        .apply(" send_num > refund_quantity "));
            }else if(StringUtils.isNotBlank(deliveryDTO.getWarehouseCode()) &&  StringUtils.isNotBlank(deliveryDTO.getShipmentCode())
             && StringUtils.isEmpty(deliveryDTO.getCustomerCode())){
                deliveries = iDeliveryService.list(new QueryWrapper<Delivery>().lambda()
                        .eq(Delivery::getWarehouseCode, deliveryDTO.getWarehouseCode())
                        .eq(Delivery::getShipmentCode, deliveryDTO.getShipmentCode())
                        .eq(Delivery::getGroupCode,UserUtil.getBranchCode())
                        .apply(" send_num > refund_quantity "));
            }else if(StringUtils.isNotBlank(deliveryDTO.getWarehouseCode()) &&  StringUtils.isEmpty(deliveryDTO.getShipmentCode())
                    && StringUtils.isNotBlank(deliveryDTO.getCustomerCode())){
                deliveries = iDeliveryService.list(new QueryWrapper<Delivery>().lambda()
                        .eq(Delivery::getWarehouseCode, deliveryDTO.getWarehouseCode())
                        .eq(Delivery::getShipmentCode, deliveryDTO.getCustomerCode())
                        .eq(Delivery::getGroupCode,UserUtil.getBranchCode())
                        .apply(" send_num > refund_quantity "));
            }

            List<DeliveryVO> vos = deliveries.stream().map(e -> {
                DeliveryVO vo = new DeliveryVO();
                BeanUtil.copyProperties(e, vo);
                return vo;
            }).collect(Collectors.toList());

            return Result.ok().data(vos);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 自动分配
     *
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "自动分配", notes = "自动分配")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryVO.class))
    @NeedLogin
    @GetMapping("/autoDistribute/{code}")
    @NoReSubmit
    public Result autoDistribute(@PathVariable String code, HttpServletRequest request) {
        try {
            return iDeliveryDistributionService.autoDistribute(code);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 批量手动生成拣货单
     *
     * @param codes
     * @param request
     * @return
     */
    @ApiOperation(value = "批量手动生成拣货单", notes = "批量手动生成拣货单", produces = MediaTypes.JSON_UTF_8)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
    })
    @NeedLogin
    @PostMapping("batchGeneratePicking")
    @NoReSubmit
    public Result batchGeneratePick(@RequestParam List<String> codes, HttpServletRequest request) {
        log.info("批量手动生成拣货单，订单号：{}", JSONUtil.toJsonStr(codes));
        if(IterUtil.isEmpty(codes)){
            return Result.error("请选择订单");
        }
        List<RLock> locks = Lists.newArrayList();
        try {
            for (String code : codes) {
                RLock l = redissonClient.getLock(getPickingLockKey(code));
                if (l.tryLock()) {
                    log.info("订单【{}】生成拣货单获得锁成功", code);
                    locks.add(l);
                } else {
                    log.error("任务【{}】生成拣货单获得锁失败", code);
                    return Result.error("不能重复生成拣货单");
                }
            }
            log.info("批量手动生成拣货单，先处理取消订单");
            //Set<String> cancelCodes = orderCancelService.deliveryOrderCancel(codes);

           /* Set<String> cancelCodes = deliveryCancelHandleService.deliveryOrderCancel(codes);
            if(IterUtil.isNotEmpty(cancelCodes)){
                return Result.error("拣货单生成失败，订单："+StrUtil.join(",",cancelCodes)+"已取消，请重新选择");
            }*/

            Map<String, Object> result = iDeliveryService.batchGeneratePicking(codes);
            Integer success = MapUtil.getInt(result, PropertyConst.SUCCESS);
            List<String> errorInfos = MapUtil.get(result, "errorInfos", List.class);
            int failNum = codes.size() - success;
            StringBuilder buffer = new StringBuilder();
            buffer.append("生成成功").append(success).append("条；失败").append(failNum).append("条；");
            if (IterUtil.isNotEmpty(errorInfos)) {
                errorInfos.forEach(e -> {
                    buffer.append("<br><font color='red'>").append(e).append("</font>");
                });
            }
            return Result.ok(buffer.toString());
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        } finally {
            try {
                locks.forEach(l -> {
                    // 判断锁不为空 && 当前线程获得到了锁
                    if (null != l && l.isLocked()) {
                        l.unlock();
                    }
                });
            } catch (Exception e) {
                log.error("释放锁失败！！", e);
            }

        }
    }


    /**
     * 任务指派分布式锁
     *
     * @param code
     * @return
     */
    private String getPickingLockKey(String code) {
        return String.format("picking-lock-%s", code);
    }


    /**
     * 获取 已分配订单 列表，非分页
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "获取 已分配订单 列表", notes = "获取 已分配订单 列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryVO.class))
    @NeedLogin
    @GetMapping("/chooseData")
    public Result chooseData(HttpServletRequest request) {
        String groupCode = UserUtil.getBranchCode();

        if(StrUtil.isBlank(groupCode)){
            throw new ServiceException("用户所属组织为空，请重新登录");
        }



            // 获取已分配、未删除的订单
            List<Delivery> deliveries = iDeliveryService.list(Wrappers.lambdaQuery(Delivery.class)
                    .eq(Delivery::getGroupCode,groupCode)
                    .eq(Delivery::getStatus, DeliveryStatusEnum.DISTRIBUTIONED.getValue()));
            return Result.ok().data(deliveries);

    }

    @ApiOperation(value = "发货单 导入 预览", notes = "发货单 导入 预览")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "filePath", value = "文件路径", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "isView", value = "是否已经预览", required = true, paramType = "query", dataType = "Integer")
    })
    @PostMapping("/deliveryView")
    @NoReSubmit
    public Result deliveryView(String filePath, Integer isView, HttpServletRequest request) {
        try {
            java.net.URL url = new java.net.URL(filePath);
            List<DeliveryExcelDTO> list = EasyExcelUtil.read(url.openStream(), DeliveryExcelDTO.class, 2);
            if (CollUtil.isEmpty(list)) {
                throw new ServiceException("文件内容为空");
            }
            if (list.size() > 25000) {
                throw new ServiceException("文件不能超过25000行！");
            }

            List<DeliveryExcelDTO> deliveryExcelDTOList = iDeliveryService.deliveryView(list);
            return new Result().data(deliveryExcelDTOList);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    @ApiOperation(value = "发货单 导入", notes = "发货单 导入")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "filePath", value = "文件路径", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "isView", value = "是否已经预览", required = true, paramType = "query", dataType = "Integer")
    })
    @PostMapping("/deliveryImport")
    @NoReSubmit
    public Result deliveryImport(HttpServletRequest request) {
        try {
            iDeliveryService.deliveryImport();
            return Result.ok();
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 发货单部分确认
     *
     * @param entity
     * @param request
     * @return
     */
    @ApiOperation(value = "发货单部分确认", notes = "发货单 发货单部分确认 预览")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @PostMapping("/partConfirm")
    public Result partConfirm(@RequestBody @Validated(Delivery.Save.class) Delivery entity, HttpServletRequest request) {
        try {
            iDeliveryService.partConfirm(entity);
            return Result.ok();
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 根据波次信息获取 出库单 列表
     *
     * @param deliveryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "根据波次获取 订单 列表", notes = "根据波次获取 订单 列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryVO.class))
    @NeedLogin
    @GetMapping("/queryDeliverylistByWave")
    public Result queryDeliverylistByWave(DeliveryDTO deliveryDTO, HttpServletRequest request) {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            String groupCode = UserUtil.getBranchCode();
            List<String> warehouseCodes = authMap.get(CommonConst.WAREHOUSE_CODES);
            List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);
            if(StrUtil.isBlank(groupCode)){
                throw new ServiceException("用户所属组织为空，请重新登录");
            }
            if(IterUtil.isEmpty(warehouseCodes)||IterUtil.isEmpty(shipmentCodes)){
                return Result.ok().data(new Page<>(deliveryDTO.getPageNum(), deliveryDTO.getPageSize()));
            }
            deliveryDTO.setGroupCode(groupCode);
            //登录账号授权的仓库过滤
            deliveryDTO.setWarehouseCodes(warehouseCodes);
            //登录账号授权的货主过滤
            deliveryDTO.setShipmentCodes(shipmentCodes);
            //请求方法为queryDeliverylistByWave时，按order_num升序排序
            deliveryDTO.setSortField("a.order_num");
            deliveryDTO.setSortType("asc");

            //根据波次进行精确查找
            // 因出库管理-拣货单管理-查看-订单详情,当在500万数据量时，查询超时，故此处改为精确查找 by liuzhenhuan 20211111 add
            deliveryDTO.setWavePickingCodeFullQuery(true);

            DeliveryVO deliveryVO = iDeliveryService.queryListTotal(deliveryDTO);
            List<DeliveryVO> outboundVOS = iDeliveryService.queryList(deliveryDTO);
            Page<DeliveryVO> returnPage = new Page<>(deliveryDTO.getPageNum(), deliveryDTO.getPageSize());
            returnPage.setRecords(outboundVOS);
            returnPage.setTotal(deliveryVO.getTotal());
            returnPage.setSumObject(deliveryVO);
            return Result.ok().data(returnPage);

    }



    /**
     * 订单处理  生成波次
     *
     * @param codes   订单编号
     * @param request
     * @return
     */
    @ApiOperation(value = "生成波次 ", notes = "生成波次")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "maxOrderQuantity", value = "最大订单量", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "isReview", value = "是否复核：0不复核，1复核", paramType = "query", dataType = "int", defaultValue = "1"),
            @ApiImplicitParam(name = "codes", value = "订单号列表", paramType = "body", dataType = "list"),
    })
    @NeedLogin
    @PostMapping("/genWave")
    @NoReSubmit
    public Result genWave(
            @RequestParam(name = "maxOrderQuantity", required = false) Integer maxOrderQuantity,
            @RequestParam(name = "isReview", defaultValue = "1") int isReview,
            @RequestBody List<String> codes,
            HttpServletRequest request) {
        log.info("生成波次，单波次最大订单数:{}，是否跳过复核(0不复核，1复核)：{}，订单号：{}", maxOrderQuantity,isReview,JSONUtil.toJsonStr(codes));
        if (IterUtil.isEmpty(codes)) {
            return Result.error("请选择要生成波次的订单！");
        }
        //TODO 生成波次的时候避免同时操作库存，暂时注释掉取消订单处理，直接过滤掉取消的订单
        //log.info("生成波次，先处理取消订单");
        //Set<String> cancelCodes = orderCancelService.deliveryOrderCancel(codes);
        //if(IterUtil.isNotEmpty(cancelCodes)){
        //    return Result.error("生成波次失败，订单："+StrUtil.join(",",cancelCodes)+"已取消，请重新选择");
        //}
        //生成波次的时候校验是否只选一个仓库
        iDeliveryService.validateSameWarehouseCode(codes);
        String temporaryCode = iDeliveryService.updateWaveStatus(codes);
        //iDeliveryService.genWave(codes, maxOrderQuantity, temporaryCode, isReview);
        waveService.genWave(codes, maxOrderQuantity, temporaryCode, isReview);
        return Result.ok("波次生成完成");
    }


    @ApiOperation(value = "取消波次 一次只能取消一个波次", notes = "取消波次  一次只能需要一个波次")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping("/cancelWaveTips")
    @NoReSubmit
    public Result cancelWaveTips(String wavePickingCode, HttpServletRequest request) {
        log.info("取消波次,取消的波次号是" + wavePickingCode);
        if (ObjectUtil.isEmpty(wavePickingCode)) {
            return Result.error("请选择要生成波次的订单！");
        }
        waveService.cancelWaveTips(wavePickingCode);
        return Result.ok("取消波次完成");
    }


    @ApiOperation(value = "取消波次 提示内容 ", notes = "取消波次 提示内容")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping("/cancelWaveTipsPrompt")
    @NoReSubmit
    public Result cancelWaveTipsPrompt(String wavePickingCode, HttpServletRequest request) {
        //波次下的订单数量
        int waveCount = this.iDeliveryService.cancelWaveTipsPrompt(wavePickingCode);
        JSONObject j = new JSONObject();
        j.set("wavePickingCode",wavePickingCode);
        j.set("waveCount",waveCount);
        return Result.ok(j);
    }


    @ApiOperation(value = "生成波次提示内容 ", notes = "生成波次提示内容")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "maxOrderQuantity", value = "最大订单量", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "codes", value = "订单号列表", paramType = "body", dataType = "list")
    })
    //@NeedLogin
    @PostMapping("/waveTips")
    @NoReSubmit
    public Result getWaveTips(@RequestParam(name = "maxOrderQuantity", required = false) Integer maxOrderQuantity,
                              @RequestBody List<String> codes,
                              HttpServletRequest request) {
        //订单数
        int orderCount = codes.size();
        //货主数量
        int shipmentCount = this.iDeliveryService.countShipment(codes);
        //承运商数量
        int logisticsCount = this.iDeliveryService.countLogistics(codes);
        //波次数量
        int waveCount = this.iDeliveryService.countWave(codes, maxOrderQuantity);
        return Result.ok(String.format(TIPS, orderCount, shipmentCount, logisticsCount, waveCount));
    }

    /**
     * 解除发货单与波次的关系
     *
     * @param entity 发货信息
     * @return
     */
    @ApiOperation(value = "解除发货单与波次的关系", notes = "解除发货单与波次的关系")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PutMapping("/releaseRelationWithPickingItem")
    public Result releaseRelationWithPickingItem(Delivery entity) {
        if (StringUtils.isBlank(entity.getCode())) {
            return Result.error("code不能为空");
        }

        int updateNum = iDeliveryService.releaseRelation(entity);
        if (updateNum == 0) {
            return Result.error("该订单无法解除与波次的关系！code:" + entity.getCode());
        } else {
            return Result.ok("解除波次关系成功,更新" + updateNum + "条数据！");
        }
    }


    /**
     * 订单处理 查询
     *
     * @param deliveryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "订单处理查询", notes = "订单处理查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = DeliveryVO.class))
    @NeedLogin
    @GetMapping("/waveList")
    public Result waveList(DeliveryDTO deliveryDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            String groupCode = UserUtil.getBranchCode();
            List<String> warehouseCodes = authMap.get(CommonConst.WAREHOUSE_CODES);
            List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);

            if(StrUtil.isBlank(groupCode)){
                throw new ServiceException("用户所属组织为空，请重新登录");
            }
            if(IterUtil.isEmpty(warehouseCodes)||IterUtil.isEmpty(shipmentCodes)){
                return Result.ok().data(new Page<>(deliveryDTO.getPageNum(), deliveryDTO.getPageSize()));
            }

            //支持多个承运商查询
            if (StrUtil.isNotEmpty(deliveryDTO.getCarrierCode())) {
                String[] carrierCodes = deliveryDTO.getCarrierCode().split(",");
                List<String> carrierCodeList = new ArrayList<>(Arrays.asList(carrierCodes));
                deliveryDTO.setCarrierCodes(carrierCodeList);
                deliveryDTO.setCarrierCode(StrUtil.EMPTY);
            }

            //排除停发城市快递展示
            if (StrUtil.isNotEmpty(deliveryDTO.getStopAreas())) {
                String[] cities = deliveryDTO.getStopAreas().split(",");
                List<String> receiverCities = new ArrayList<>(Arrays.asList(cities));
                deliveryDTO.setReceiverCities(receiverCities);
            }

            //排除停发区县（针对直辖市）快递展示
            if (StrUtil.isNotEmpty(deliveryDTO.getStopDistricts())) {
                String[] districts = deliveryDTO.getStopDistricts().split(",");
                List<String> stopDistrictList = new ArrayList<>(Arrays.asList(districts));
                deliveryDTO.setStopDistrictList(stopDistrictList);
            }
            deliveryDTO.setGroupCode(groupCode);
            //登录账号授权的仓库过滤
            deliveryDTO.setWarehouseCodes(warehouseCodes);
            //登录账号授权的货主过滤
            deliveryDTO.setShipmentCodes(shipmentCodes);
            deliveryDTO.setIsCancel(NumConst.NUM_ZERO);
            iDeliveryService.constructParams(deliveryDTO);
            DeliveryVO deliveryVO = iDeliveryService.queryWaveListSum(deliveryDTO);
            List<DeliveryVO> deliveryVOS = iDeliveryService.queryWaveList(deliveryDTO);
            Page<DeliveryVO>  returnPage = new Page<>(deliveryDTO.getPageNum(), deliveryDTO.getPageSize());
            returnPage.setRecords(deliveryVOS);
            returnPage.setTotal(deliveryVO.getTotal());
            returnPage.setSumObject(deliveryVO);
            return Result.ok().data(returnPage);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 打印面单
     *
     * @param deliveryCodes
     * @param request
     * @return
     */
    @ApiOperation(value = "打印面单", notes = "打印面单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/printExpress")
    public Result printExpress(@RequestBody List<String> deliveryCodes, HttpServletRequest request) {
        //TODO 处理取消订单
        log.info("打印面单，订单号：{}", JSONUtil.toJsonStr(deliveryCodes));
        if(IterUtil.isEmpty(deliveryCodes)){
            return Result.error("请选择订单");
        }
        log.info("打印面单，先处理取消订单");
        //Set<String> cancelCodes = orderCancelService.deliveryOrderCancel(deliveryCodes);

       /* Set<String> cancelCodes = deliveryCancelHandleService.deliveryOrderCancel(deliveryCodes);
        if(IterUtil.isNotEmpty(cancelCodes)){
            return Result.error("打印面单失败，订单："+StrUtil.join(",",cancelCodes)+"已取消，请重新选择");
        }*/
        List<DeliveryVO> deliveryVOList = iDeliveryService.printExpress(deliveryCodes);
        return Result.ok().data(deliveryVOList);
    }


    @ApiOperation(value = "获取枚举类信息", notes = "获取枚举类信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping("/getEnumList")
    public Result getEnumList(@RequestParam(name = "type") String type, HttpServletRequest request) {
        try {
            List<Map<String, Object>> mapList = iDeliveryService.getEnumList(type);
            return Result.ok().data(mapList);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 批量获取面单号
     *
     * @param deliveryCodes
     * @return
     */
    @ApiOperation(value = "批量获取面单号", notes = "批量获取面单号")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/batchGetWaybillCode")
    public Result batchGetWaybillCode(@RequestBody List<String> deliveryCodes) {
        log.info("批量获取面单号，订单号：{}", JSONUtil.toJsonStr(deliveryCodes));
        if(IterUtil.isEmpty(deliveryCodes)){
            return Result.error("请选择订单");
        }

//        int sucessNum = 0;
//        int failureNum = 0;
        int groupSize = 1;
        int deliveryCodesSize = 300;

        String groupCode = UserUtil.getBranchCode();

        log.info("批量获取面单号，过滤掉执行中后的订单号：{}", JSONUtil.toJsonStr(deliveryCodes));
        if (deliveryCodes.size() > deliveryCodesSize) {
            throw new ServiceException("获取面单出现异常，获取面单时订单不要超过" + deliveryCodesSize + "条");
        }

        //过滤掉执行中的订单
        List<Delivery> deliveryList = iDeliveryService.list(new LambdaQueryWrapper<Delivery>().select(Delivery::getCode, Delivery::getTaskStatus)
                .in(Delivery::getCode, deliveryCodes)).stream().filter(e -> !CommonConst.STR_TWO.equals(e.getTaskStatus()))
                .collect(Collectors.toList());
        deliveryCodes = deliveryList.stream().map(Delivery::getCode).collect(Collectors.toList());

        if (IterUtil.isEmpty(deliveryCodes)) {
            throw new ServiceException("获取面单出现异常，所选订单任务状态不能都是执行中");
        }
        //将订单任务状态更新为执行中
        iDeliveryService.update(new LambdaUpdateWrapper<Delivery>()
                .in(Delivery::getCode, deliveryCodes).eq(Delivery::getGroupCode, groupCode)
                .set(Delivery::getTaskStatus, CommonConst.STR_TWO)
        );
        //获取面单异常，尝试将订单以每两个一组，重新获取面单
        List<List<String>> codessList = Lists.partition(deliveryCodes, groupSize);
        for (List<String> codes : codessList) {
            try {
                tmsWaybillUpdateService.batchGetWaybillCode(codes,groupCode);
//                sucessNum += codes.size();
            } catch (Exception ex) {
                log.error("获取面单异常，{}",ex.getMessage());
//                failureNum += codes.size();
            }
        }
        return Result.ok("获取面单请求处理中，请稍后刷新列表。");
//        return Result.ok("获取面单成功" + sucessNum + "条，失败"  + failureNum + "条");
    }

    /**
     * 批量 更改承运商
     *
     * @param deliveryDTO
     * @return
     */
    @ApiOperation(value = "批量 更改承运商", notes = "批量 更改承运商")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/changeCarrier")
    public Result changeCarrier(@RequestBody DeliveryDTO deliveryDTO) {
        List<String> deliveryCodes = deliveryDTO.getDeliveryCodes();
        String carrierCode = deliveryDTO.getCarrierCode();
        if(IterUtil.isEmpty(deliveryCodes)){
            return Result.error("请选择订单");
        }
        log.info("批量获取面单号，先处理取消订单");
        Set<String> cancelCodes = deliveryCancelHandleService.deliveryOrderCancel(deliveryCodes);
        if(IterUtil.isNotEmpty(cancelCodes)){
            return Result.error("获取运单号失败，订单："+StrUtil.join(",",cancelCodes)+"已取消，请重新选择");
        }
        Result result = tmsWaybillUpdateService.changeCarrier(deliveryCodes, carrierCode);
        return result;
    }





    /**
     * 订单处理页面-商品查询， 根据入驻商、商品分组，查询已分配的订单明细信息
     *
     * @param waveQueryGoodsDTO
     * @return
     */
    @ApiOperation(value = "订单处理页面-商品查询", notes = "订单处理页面-商品查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping("/waveQueryGoods")
    public Result waveQueryGoods(WaveQueryGoodsDTO waveQueryGoodsDTO) {
        //校验授权仓库code和货主code不能为空
        Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
        String groupCode = UserUtil.getBranchCode();
        List<String> warehouseCodes = authMap.get(CommonConst.WAREHOUSE_CODES);
        List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);

        if(StrUtil.isBlank(groupCode)){
            throw new ServiceException("用户所属组织为空，请重新登录");
        }
        if(IterUtil.isEmpty(warehouseCodes)||IterUtil.isEmpty(shipmentCodes)){
            return Result.ok().data(new Page<>(waveQueryGoodsDTO.getPageNum(), waveQueryGoodsDTO.getPageSize()));
        }
        waveQueryGoodsDTO.setGroupCode(groupCode);
        //登录账号授权的仓库过滤
        waveQueryGoodsDTO.setWarehouseCodes(warehouseCodes);
        //登录账号授权的货主过滤
        waveQueryGoodsDTO.setShipmentCodes(shipmentCodes);

        WaveQueryGoodsVO waveQueryGoodsVO = iDeliveryService.waveQueryGoodsSum(waveQueryGoodsDTO);
        List<WaveQueryGoodsVO> waveQueryGoodsVoS = iDeliveryService.waveQueryGoods(waveQueryGoodsDTO);
        Page<WaveQueryGoodsVO> returnPage = new Page<>(waveQueryGoodsDTO.getPageNum(), waveQueryGoodsDTO.getPageSize());
        returnPage.setRecords(waveQueryGoodsVoS);
        returnPage.setTotal(waveQueryGoodsVO.getTotal());
        return Result.ok().data(returnPage);

    }


    /**
     * 订单处理页面-爆品商品查询， 根据入驻商、商品分组，查询已分配的订单明细信息
     *
     * @param waveQueryGoodsDTO
     * @return
     */
    @ApiOperation(value = "订单处理页面-爆品商品查询", notes = "订单处理页面-爆品商品查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping("/waveQueryHotGoods")
    public Result waveQueryHotGoods(WaveQueryGoodsDTO waveQueryGoodsDTO) {
        //校验授权仓库code和货主code不能为空
        Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
        String groupCode = UserUtil.getBranchCode();
        List<String> warehouseCodes = authMap.get(CommonConst.WAREHOUSE_CODES);
        List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);

        if(StrUtil.isBlank(groupCode)){
            throw new ServiceException("用户所属组织为空，请重新登录");
        }
        if(IterUtil.isEmpty(warehouseCodes)||IterUtil.isEmpty(shipmentCodes)){
            return Result.ok().data(new Page<>(waveQueryGoodsDTO.getPageNum(), waveQueryGoodsDTO.getPageSize()));
        }
        //登录账号授权的仓库过滤
        waveQueryGoodsDTO.setWarehouseCodes(warehouseCodes);
        //登录账号授权的货主过滤
        waveQueryGoodsDTO.setShipmentCodes(shipmentCodes);
        WaveQueryGoodsVO waveQueryGoodsVO = iDeliveryService.waveQueryHotGoodsSum(waveQueryGoodsDTO);

        List<WaveQueryGoodsVO> waveQueryGoodsVoS = iDeliveryService.waveQueryHotGoods(waveQueryGoodsDTO);
        Page<WaveQueryGoodsVO> returnPage = new Page<>(waveQueryGoodsDTO.getPageNum(), waveQueryGoodsDTO.getPageSize());
        returnPage.setRecords(waveQueryGoodsVoS);
        returnPage.setTotal(waveQueryGoodsVO.getTotal());
        return Result.ok().data(returnPage);

    }


    @ApiOperation(value = "取消电子面单", notes = "取消电子面单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping("/tmsWaybillDiscard/{deliveryCode}")
    public Result tmsWaybillDiscard(@PathVariable String deliveryCode) {
        tmsWaybillUpdateService.tmsWaybillDiscard(deliveryCode);
        return Result.ok();
    }


    @ApiOperation(value = "面单打印次数增加", notes = "面单打印次数增加1")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/updatePrintCount/{deliveryCode}")
    public Result updatePrintCount(@PathVariable String deliveryCode) {
        iDeliveryService.updatePrintCount(deliveryCode);
        return Result.ok();
    }

    @ApiOperation(value = "批量更新面单打印次数增加", notes = "批量更新面单打印次数增加1")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/batchUpdatePrintCount")
    public Result batchUpdatePrintCount(@RequestBody List<DeliveryDTO> deliveryDTOS) {
        iDeliveryService.batchUpdatePrintCount(deliveryDTOS);
        return Result.ok();
    }


    @ApiOperation(value = "打印面单的日志信息", notes = "打印面单的日志信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/printLog")
    public Result printLog(@RequestBody String logs) {
       log.info("打印面单的日志信息为" + JSONUtil.toJsonStr(logs));
       log.error("打印面单的日志信息为" + JSONUtil.toJsonStr(logs));
       return Result.ok();
    }

    /**
     * 获取 出库单 列表
     *
     * @param deliveryDTO
     * @param request
     * @return
     */





    @ApiOperation(value = "更新订单状态 ", notes = "更新订单状态，处理作废单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
    })
    @NeedLogin
    @GetMapping("/updateDeliveryStatus")
    public Result updateDeliveryStatus(
            HttpServletRequest request) {
        //校验授权仓库code和货主code不能为空
        Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
        String warehouseCode = UserUtil.getLoginWarehouseCodeOrShipmentCode();
        String groupCode = UserUtil.getBranchCode();
        List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);
        deliveryCancelHandleService.deliveryOrderCancel(warehouseCode, groupCode, shipmentCodes);
        return Result.ok("订单状态更新完成");
    }







    @ApiOperation(value = "取消订单处理", notes = "取消订单处理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping("/cancelHandler")
    public Result cancelHandler(HttpServletRequest request) {
        //校验授权仓库code和货主code不能为空
        Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
        String warehouseCode = UserUtil.getLoginWarehouseCodeOrShipmentCode();
        String groupCode = UserUtil.getBranchCode();
        List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);
        //iDeliveryService.updateCanceledDeliveryStatus(groupCode, warehouseCode);

        deliveryCancelHandleService.deliveryOrderCancel(warehouseCode, groupCode, shipmentCodes);
        return Result.ok("取消订单处理完成");
    }

    @ApiOperation(value = "获取积压订单数量", notes = "获取积压订单数量")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping("/getBacklogOrderNum")
    public Result getBacklogOrderNum(HttpServletRequest request) {
        //校验授权仓库code和货主code不能为空
        ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
        return iDeliveryService.getBacklogOrderNum();
    }

    @ApiOperation(value = "电商仓大数据订单列表", notes = "电商仓大数据订单列表，默认100条")
    @GetMapping("/bd")
    public List<DeliveryVO> bdList(DeliveryDTO deliveryDTO, HttpServletRequest request) {
        if(deliveryDTO.getPageNum()==null){
            deliveryDTO.setPageNum(1);
        } if(deliveryDTO.getPageSize()==null){
            deliveryDTO.setPageNum(100);
        }
        List<DeliveryVO> outboundVos = iDeliveryService.queryBdList(deliveryDTO);

        return outboundVos;
    }



    @ApiOperation(value = "批量更新面单打印次数,前端传更新次数", notes = "批量更新面单打印次数,前端传更新次数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/batchUpdatePrintNum")
    public Result batchUpdatePrintNum(@RequestParam(value = "codes") List<String> codes, @RequestParam(value = "printNum")Integer printNum) {
        iDeliveryService.batchUpdatePrintCount(codes,printNum);
        return Result.ok();
    }

    @ApiOperation(value = "批量更新面单打印次数,前端传更新次数", notes = "批量更新面单打印次数,前端传更新次数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping("/chooseSourcePlatformList")
    public Result chooseSourcePlatformList() {
        List<DeliveryVO> deliveryVOList = iDeliveryService.chooseSourcePlatformList();
        return Result.ok().data(deliveryVOList);
    }



}
